package view.micro
{
	import events.BattleEvent;
	import events.GuiEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import model.micro.Battle;
	import model.micro.FieldUnit;
	import model.micro.projectiles.Projectile;
	import util.Settings;
	import view.micro.background.BattleBackgroundSprite;
	import view.microgui.AttackIconManager;
	
	/**
	 * A sprite that draws the battle.
	 */
	public class BattleSprite extends Sprite implements IMicroSprite
	{
		public var battle:Battle;
		private var attack_icon_manager:AttackIconManager;
		private var camera:Camera;
		
		/**
		 * Create a new battle sprite for a battle.
		 * @param	battle
		 */
		public function BattleSprite(battle:Battle)
		{
			this.battle = battle;
			addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true);
		}
		
		/**
		 * Initialized the BattleSprite with data from the battle.
		 * @param	e
		 */
		private function init(e:Event):void
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			addChild(new BattleBackgroundSprite(battle));
			addChild(new FortressSprite(battle.fortress));
			
			attack_icon_manager = new AttackIconManager();
			addChild(attack_icon_manager);
			
			for each (var unit:FieldUnit in battle.attack_field_units)
			{
				addUnit(unit);
			}
			
			camera = new Camera(stage);
			x = camera.sprite_x;
			y = camera.sprite_y
			scaleX = camera.sprite_scale
			scaleY = -camera.sprite_scale;
			
			battle.addEventListener(BattleEvent.PROJECTILE_CREATED, projectileCreated, false, 0, true);
			battle.addEventListener(BattleEvent.GARRISON_DEPLOYED, garrisonDeployed, false, 0, true);
			battle.addEventListener(GuiEvent.CAMERA_SCROLL, onCameraScroll);
			battle.addEventListener(GuiEvent.CAMERA_SCROLL_TO, onCameraScrollTo);
			battle.addEventListener(GuiEvent.CAMERA_ZOOM, onCameraZoom);
			battle.addEventListener(GuiEvent.CAMERA_ZOOM_TO, onCameraZoomTo);
			
			// forward events
			addEventListener(MouseEvent.MOUSE_DOWN, forwardEvent);
			addEventListener(MouseEvent.MOUSE_UP, forwardEvent);
			addEventListener(MouseEvent.RIGHT_MOUSE_UP, forwardEvent);
			addEventListener(MouseEvent.RIGHT_MOUSE_DOWN, forwardEvent);
			addEventListener(MouseEvent.MOUSE_WHEEL, forwardEvent);
			addEventListener(BattleEvent.UNIT_SELECTED, forwardEvent);
		}
		
		private function onCameraZoomTo(e:GuiEvent):void
		{
			camera.zoomTo(e.data['z']);
		}
		
		private function onCameraZoom(e:GuiEvent):void
		{
			camera.zoom(e.data['z']);
		}
		
		private function onCameraScrollTo(e:GuiEvent):void
		{
			camera.scrollTo(e.data['x'], e.data['y'], e.data['center'] || false);
		}
		
		private function onCameraScroll(e:GuiEvent):void
		{
			camera.scroll(e.data['x'], e.data['y']);
		}
		
		private function forwardEvent(e:Event):void
		{
			if (e is MouseEvent)
			{
				// set local coordinates relative to the battle sprite
				var e2:MouseEvent = e as MouseEvent;
				var point:Point = globalToLocal(new Point(e2.stageX, e2.stageY));
				e2.localX = point.x;
				e2.localY = point.y;
			}
			battle.dispatchEvent(e);
		}
		
		/**
		 * Called when a unit is deployed from the garrison.
		 * @param	e
		 */
		private function garrisonDeployed(e:BattleEvent):void
		{
			addUnit(e.data as FieldUnit);
		}
		
		private function addUnit(unit:FieldUnit):FieldUnit
		{
			var unit_sprite:FieldUnitSprite = new FieldUnitSprite(unit);
			addChild(unit_sprite);
			attack_icon_manager.addUnit(unit_sprite);
			return unit;
		}
		
		/**
		 * Called when a projectile is created.
		 * @param	e
		 */
		private function projectileCreated(e:BattleEvent):void
		{
			addChild(new ArrowSprite(e.data as Projectile));
		}
		
		/**
		 * Update the view to match current state of the battle.
		 */
		public function update():void
		{
			// update camera
			camera.update();
			x = camera.sprite_x;
			y = camera.sprite_y;
			scaleX = camera.sprite_scale;
			scaleY = -camera.sprite_scale;
			
			// loop through children
			for (var i:int = numChildren - 1; i >= 0; i--)
			{
				var child:IMicroSprite = (getChildAt(i) as IMicroSprite);
				if (child != null)
				{
					child.update();
					if (child.readyToRemove())
					{
						removeChildAt(i);
					}
				}
			}
		}
		
		/**
		 * Called when this can be deleted.
		 * @return
		 */
		public function readyToRemove():Boolean
		{
			return false;
		}
	
	}
}